/*	Copyright (c) 2019 Jean-Marc VIGLINO,
  released under the CeCILL-B license (French BSD license)
  (http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
*/

//import ol_ext_inherits from '../util/ext'
import ol_control_Control from 'ol/control/Control'
import {getCenter as ol_extent_getCenter} from 'ol/extent'
import ol_Map from 'ol/Map'
import ol_View from 'ol/View'
import {transformExtent as ol_proj_transformExtent} from 'ol/proj'
import {ol_ext_inherits} from '../util/ext'
import ol_ext_element from 'ol-ext/util/element'

/** A control to jump from one zone to another.
 * @constructor
 * @fires select
 * @extends {ol_control_Control}
 * @param {Object=} options Control options.
 *	@param {string} options.className class name
 *  @param {Array<any>} options.zone an array of zone: { name, extent (in EPSG:4326) }
 *	@param {ol.layer.Layer|function} options.layer layer to display in the control or a function that takes a zone and returns a layer to add to the control
 *	@param {ol.ProjectionLike} options.projection projection of the control, Default is EPSG:3857 (Spherical Mercator).
 *  @param {bolean} options.centerOnClick center on click when a zone is clicked (or listen to 'select' event to do something), default true
 */
var ol_control_MapZone = function(options) {
  if (!options) options={};
  
  var element = document.createElement("div");
  if (options.target) {
    element = ol_ext_element.create('DIV', {
      className: options.className || "ol-mapzone"
    });
  } else {
    element = ol_ext_element.create('DIV', {
      className: (options.className || "ol-mapzone") +' ol-unselectable ol-control ol-collapsed'
    });
    var bt = ol_ext_element.create('BUTTON', {
      type: 'button',
      on: {
        'click': function() {
          element.classList.toggle("ol-collapsed");
          maps.forEach(function (m) {
            m.updateSize();
          });
        }.bind(this)
      },
      parent: element
    });
    ol_ext_element.create('I', {
      parent: bt
    });
  }

  // Parent control
  ol_control_Control.call(this, {
    element: element,
    target: options.target
  });
  this.set('centerOnClick', options.centerOnClick);

  // Create maps
  var maps = this._maps = [];
  this._projection = options.projection;
  this._layer = options.layer;
  options.zones.forEach(this.addZone.bind(this));

  // Refresh the maps
  setTimeout(function() {
    maps.forEach(function (m) {
      m.updateSize();
    });
  });
};
ol_ext_inherits(ol_control_MapZone, ol_control_Control);

/** Collapse the control
 * @param {boolean} b
 */
ol_control_MapZone.prototype.setCollapsed = function (b) {
  if (b) {
    this.element.classList.remove('ol-collapsed');
    // Force map rendering
    this.getMaps().forEach(function (m) {
      m.updateSize();
    });
  } else {
    this.element.classList.add('ol-collapsed');
  }
};

/** Get control collapsed
 * @return {boolean} 
 */
ol_control_MapZone.prototype.getCollapsed = function () {
  return this.element.classList.contains('ol-collapsed');
};

/** Set the control visibility (collapsed)
 * @param {boolean} b
 * @deprecated use setCollapsed instead
 */
ol_control_MapZone.prototype.setVisible = ol_control_MapZone.prototype.setCollapsed;
 
/** Get associated maps
 * @return {ol.Map}
 */
ol_control_MapZone.prototype.getMaps = function () {
  return this._maps;
};

/** Get nb zone */
ol_control_MapZone.prototype.getLength = function () {
  return this._maps.length;
};

/** Add a new zone to the control 
 * @param {Object} z 
 *  @param {string} title
 *  @param {ol.extent} extent if map is not defined
 *  @param {ol.Map} map if map is defined use the map extent 
 *  @param {ol.layer.Layer} [layer] layer of the zone, default use default control layer
 */
ol_control_MapZone.prototype.addZone = function (z) {
  var view = new ol_View({ zoom: 6, center: [0,0], projection: this._projection });
  var extent;
  if (z.map) {
    extent = ol_proj_transformExtent(z.map.getView().calculateExtent(), z.map.getView().getProjection(), view.getProjection()) ;
  } else {
    extent = ol_proj_transformExtent(z.extent, 'EPSG:4326', view.getProjection());
  }
  // console.log(extent, z.extent)
  var div = ol_ext_element.create('DIV', {
    className: 'ol-mapzonezone',
    parent: this.element,
    click : function() {
      // Get index
      var index = -1;
      this._maps.forEach(function(m, i) {
        if (m.get('zone') === z) {
          index = i;
        }
      })
      this.dispatchEvent({
        type: 'select',
        zone: z,
        index: index,
        coordinate: ol_extent_getCenter(extent),
        extent: extent
      });
      if (this.get('centerOnClick') !== false) {
        this.getMap().getView().fit(extent);
      }
      this.setVisible(false);
    }.bind(this)
  });
  var layer;
  if (z.layer) {
    layer = z.layer;
  } else if (typeof(this._layer) === 'function') {
    layer = this._layer(z);
  } else {
    // Try to clone the layer
    layer = new this._layer.constructor({
      source: this._layer.getSource()
    });
  }
  var map = new ol_Map({
    target: div,
    view: view,
    controls: [],
    interactions:[],
    layers: [layer]
  });
  map.set('zone', z);
  this._maps.push(map);
  view.fit(extent);
  // Name
  ol_ext_element.create('P', {
    html: z.title,
    parent: div
  });
};

/** Remove a zone from the control 
 * @param {number} index
 */
ol_control_MapZone.prototype.removeZone = function (index) {
  var z = this.element.querySelectorAll('.ol-mapzonezone')[index];
  if (z) {
    z.remove();
    this._maps.splice(index, 1);
  }
};

/** Pre-defined zones */
ol_control_MapZone.zones = {};
  
/** French overseas departments  */
ol_control_MapZone.zones.DOM = [{
  "title": "Guadeloupe",
  "extent": [ -61.898594315312444, 15.75623038647845, -60.957887532935324, 16.575317670979473 ]
},{
  "title": "Guyane",
  "extent": [ -54.72525931072715, 2.1603763430019, -51.528236062921344, 5.7984307809552575 ]
},{
  "title": "Martinique",
  "extent": [ -61.257556528564756, 14.387506317407514, -60.76934912110432, 14.895067461729951 ]
},{
  "title": "Mayotte",
  "extent": [ 44.959844536967815, -13.01674138212816, 45.35328866510648, -12.65521942207829 ]
},{
  "title": "La réunion",
  "extent": [ 55.17059012967656, -21.407680069231688, 55.88195702001797, -20.85560221637526 ]
}];

/** French overseas territories */
ol_control_MapZone.zones.TOM = [{
  "title": "Polynésie Française",
  "extent": [ 206.23664226630862, -22.189040615809787, 221.85920743981987, -10.835039595040698 ]
},{
  "title": "Nouvelle Calédonie",
  "extent": [ 163.76420580160925, -22.581641092751838, 167.66984709498706, -19.816411635668445 ]
},{
  "title": "St-Pierre et Miquelon",
  "extent": [ -56.453698765748676, 46.74449858188555, -56.0980198121544, 47.14669874229787 ]
},{
  "title": "Wallis et Futuna",
  "extent": [ 181.7588623143665, -14.7341169873267, 183.95612353301715, -13.134720799175085 ]
},{
  "title": "St-Martin St-Barthélemy",
  "extent": [ -63.1726389501678, 17.806097291313506, -62.7606535945649, 18.13267688837938 ]
}];

/** French overseas departments and territories */
ol_control_MapZone.zones.DOMTOM = [{
  title: 'Métropole',
  extent: [ -5.318421740712579, 41.16082274292913, 9.73284186155716, 51.21957336557702 ]
}].concat(ol_control_MapZone.zones.DOM, ol_control_MapZone.zones.TOM);

export default ol_control_MapZone
